#pragma once

#include <iostream>
#include <mutex>
#include <boost/asio.hpp>
#include <boost/bind.hpp>


class SerialControl
{
private:
    std::string serial_com = "/dev/ttyUSB0";     // 串口端口
    std::string baudrate = "115200";       // 串口波特率


    std::mutex mt;                          // buffer变量的锁
    #define RECV_BUFFER_LEN 4096
    char recv_buffer[RECV_BUFFER_LEN];      // 4K的接收buffer

    // 串口是否打开
    bool serial_open = false;
    // 系统运行标志位
    bool *system_running = nullptr;
    // 键盘是否可以输入指令
    bool keyboard_writable = true;
    // 是否显示接收到的数据
    bool receive_displayable = true;


    boost::asio::io_service iosev;
    boost::asio::serial_port *sp;
    boost::system::error_code ec;


public:
    SerialControl(){};
    SerialControl(std::string serial_com, std::string baudrate, bool *system_running);
    ~SerialControl();

    // 连接到串口
    bool connect(void);

    // 配置串口与终端输出
    bool config(int vim = 1, int vtime = 0);

    // 给thread封装一层，不然会报错
    static void start_write_thread(SerialControl *handle);

    // 读写线程分开，写线程
    void write_thread(void);

    // 给thread封装一层，不然会报错
    static void start_read_thread(SerialControl *handle);

    // 读写线程分开，读线程
    void read_thread(void);

    // 给thread封装一层，不然会报错
    static void static_read_write_thread(SerialControl *handle);

    // 通过多线程的方式读写串口
    void read_write_thread(void);

    // 提取接收缓存中的数据
    void read_data(std::string &buff);

    // 发送指定长度的数据
    size_t send_data(const void *data, size_t len);

    // 通过串口执行命令，带回车
    void send_cmd(std::string &cmd);

    // 发送回车
    void send_key_enter(void);

    // 设置键盘是否可以输入
    void set_keyboard_writable(bool keyboard_writable);

    // 设置是否显示接收到的数据
    void set_receive_displayable(bool receive_displayable);

};
